Skip to main content

加密 Secrets 资源:Sealed Secrets 使用指南

· 14 min read

Sealed Secrets是一种在版本控制中存储加密的Kubernetes秘密的解决方案。

在这篇博文中,我们将学习如何安装和使用它。

安装

Sealed Secrets 由两个部分组成:

  • Client-side CLI tool: kubeseal
    客户端CLI工具 kubeseal,用于加密机密和创建密封机密
  • Server-side controller
    服务器端控制器,用于解密 SealedSecret CRD 和 创建 secrets

controller 安装

sealed-secrets artifacthub

添加仓库并将其安装到 kube-system 命名空间:

Repo=https://bitnami-labs.github.io/sealed-secrets
Chart=sealed-secrets
Target=sealed-secrets
NameSpace=kube-system

helm upgrade --install ${Target} ${Chart} \
--repo ${Repo} \
--namespace ${NameSpace} \
--create-namespace \
--set-string fullnameOverride=sealed-secrets-controller
# --set customKey=YOUR_CUSTOM_KEY_HERE
# key-renew-period=0
  • --namespace 将其安装在kube-systems使得kubeseal命令不用显示声明--controller-namespace=kube-systems
  • --set-string fullnameOverride=sealed-secrets-controller 这个参数会 kube-system 命名空间里创建 sealed-secrets-controller service 使得 kubeseal 命令不用显示声明 controller-name=sealed-secrets-controller
  • 控制器在首次部署时会生成自己的证书,它还会为您管理续订。但您也可以自带证书,以便控制器也可以使用它们。
  • 控制器使用任何标记为 sealedsecrets.bitnami.com/sealed-secrets-key=active 的密钥中包含的证书,该密钥必须与控制器位于同一命名空间中。可以有多个这样的秘密。

kubeseal 安装

kubeseal CLI 使用当前 kubectl 上下文访问集群。在继续之前,请确保 kubectl 已连接到应安装 Sealed Secrets 的群集。

# macos
brew install kubeseal
# linux
wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.13.1/kubeseal-linux-amd64 -O kubeseal
sudo install -m 755 kubeseal /usr/local/bin/kubeseal

工作原理

1

启动时,控制器会在其命名空间中搜索带有 sealedsecrets.bitnami.com/sealed-secrets-key 标签的 Secret 读取其中存放的私钥/公钥对。如果找不到,控制器则会生成一个新的 4096 位 RSA 密钥对,并在其命名空间中创建新的 Secret 将其保存其中。随后会将公钥部分打印到输出日志中。您可以使用以下命令以 YAML 格式查看此 Secret(包含公有/私有密钥对)的内容:

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml

配套的 CLI 工具 kubeseal 使用公钥加密 Secret 资源生成 SealedSecret 定制化资源定义 (CRD)we文件。将 SealedSecret 自定义资源部署到 Kubernetes 集群时,控制器会拾取该资源,然后使用私钥将其解封并创建一个 Secret 资源。加密和解密时会使用 SealedSecret 的命名空间/名称作为输入参数,这样可以确保 SealedSecret 和 Secret 严格绑定到相同的命名空间和名称。

kubeseal 可以通过 Kubernetes API 服务器与控制器进行通信,并在运行时检索加密 Secret 所需的公钥。您也可以从控制器下载公钥并保存在本地以便离线使用。

基础使用

SealedSecret 作用域

  • SealedSecret 和 Secret 必须具有相同的命名空间和名称。此功能可防止同一集群上的其他用户重复使用您密封的密钥。
# 默认限制命名空间
kubeseal --format yaml < mysecret.yaml > mysealedsecret.yaml
# --scope 全局可用生成的密文可以在整个集群中使用,而不是仅限于特定的命名空间
kubeseal --format yaml --scope cluster-wide < mysecret.yaml > mysealedsecret2.yaml

加密 secret

kubeseal CLI 将 Kubernetes Secret 清单作为输入,对其进行加密并输出清单 SealedSecret 。

在本教程中,我们将使用此机密清单作为输入:

apiVersion: v1
kind: Secret
metadata:
creationTimestamp: null
name: my-secret
data:
password: YmFy
username: Zm9v

将清单存储在名为 secret.yaml and encrypt it 的文件中:

cat secret.yaml | kubeseal \
--controller-namespace kube-system \
--controller-name sealed-secrets \
--format yaml \
> sealed-secret.yaml

sealed-secret.yaml 文件的内容应如下所示:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: my-secret
namespace: default
spec:
encryptedData:
password: AgA...
username: AgA...
template:
metadata:
creationTimestamp: null
name: my-secret
namespace: default

我们现在应该有秘密在里面 secret.yaml ,把密封的秘密在里面 sealed-secret.yaml 。此时已不再需要与该 Secret 有关的 YAML 清单,您可以将其删除。SealedSecret 将会是唯一被部署到集群的资源,如下所示:

请注意,原始 Secret 中的键(即username 和 password)在 SealedSecret 中未被加密,只有这些键对应的值被加密。您可以根据需要在 SealedSecret YAML 文件中更改这些键的名称,并且仍能够将更改后的键成功部署到集群中。但是,您不能更改 SealedSecret 的 name 和 namespace,否则会使 SealedSecret 无效,因为原始 Secret 的名称和命名空间会在加密过程中用作输入参数。这种方式提供了额外的保护措施,即使用户获得了对 SealedSecret 的 YAML 清单的访问权限(此 SealedSecret 是为在用户无权访问的 Kubernetes 集群中的特定命名空间而创建),他们也无法仅编辑清单和将 SealedSecret 部署到不同的命名空间(包括同一集群中的不同命名空间)。

为了部署密封的密钥,我们使用 kubectl 应用清单:

kubectl apply -f sealed-secret.yaml

集群中的控制器会注意到已创建资源 SealedSecret ,对其进行解密并创建已 Secret 解密的 .

让我们获取密钥以确保控制器已成功解封unsealed 它:

kubectl get secret my-secret -o yaml

数据应包含我们的 base64 编码用户名和密码:

...
data:
password: YmFy
username: Zm9v
...

一切都很顺利。秘密已被成功解封unsealed。

进阶指南

自定义密钥

export PRIVATEKEY="default.key"
export PUBLICKEY="default.crt"
export NAMESPACE="sealed-secrets"
export SECRETNAME="mycustomkeys"
export DAYS="3650"

生成新的 RSA 密钥对(证书)

openssl req -x509 -days ${DAYS} -nodes -newkey rsa:4096 -keyout "$PRIVATEKEY" -out "$PUBLICKEY" -subj "/CN=sealed-secret/O=sealed-secret"

使用您最近创建的 RSA 密钥对创建 tls k8s 密钥

kubectl -n "$NAMESPACE" create secret tls "$SECRETNAME" --cert="$PUBLICKEY" --key="$PRIVATEKEY"
kubectl -n "$NAMESPACE" label secret "$SECRETNAME" sealedsecrets.bitnami.com/sealed-secrets-key=active

需要删除控制器 Pod 才能选择新密钥

kubectl -n  "$NAMESPACE" delete pod -l name=sealed-secrets-controller

查看控制器日志中的新证书(私钥)

kubectl -n "$NAMESPACE" logs -l name=sealed-secrets-controller

controller version: v0.12.1+dirty
2020/06/09 14:30:45 Starting sealed-secrets controller version: v0.12.1+dirty
2020/06/09 14:30:45 Searching for existing private keys
2020/06/09 14:30:45 ----- sealed-secrets-key5rxd9
2020/06/09 14:30:45 ----- mycustomkeys
2020/06/09 14:30:45 HTTP server serving on :8080

现在,您可以尝试使用自己的证书来密封密钥,而不是使用控制器提供的证书。

使用 --cert 以下标志使用自己的证书(密钥):

kubeseal --cert "./${PUBLICKEY}" --scope cluster-wide < mysecret.yaml | kubectl apply -f-

我们可以看到秘密已经成功解封

kubectl -n "$NAMESPACE" logs -l name=sealed-secrets-controller

controller version: v0.12.1+dirty
2020/06/09 14:30:45 Starting sealed-secrets controller version: v0.12.1+dirty
2020/06/09 14:30:45 Searching for existing private keys
2020/06/09 14:30:45 ----- sealed-secrets-key5rxd9
2020/06/09 14:30:45 ----- mycustomkeys
2020/06/09 14:30:45 HTTP server serving on :8080
2020/06/09 14:37:55 Updating test-namespace/mysecret
2020/06/09 14:37:55 Event(v1.ObjectReference{Kind:"SealedSecret", Namespace:"test-namespace", Name:"mysecret", UID:"f3a6c537-d254-4c06-b08f-ab9548f28f5b", APIVersion:"bitnami.com/v1alpha1", ResourceVersion:"20469957", FieldPath:""}): type: 'Normal' reason: 'Unsealed' SealedSecret unsealed successfully

PRIVATEKEY 是您的私钥,控制器使用它来解封您的密钥。不要与任何你不信任的人分享它,并将其保存在一个安全的地方!

导出公钥和加密

kubeseal --fetch-cert > public-key-cert.pem

然后使用 kubeseal 使用公钥文件创建 SealedSecret CRD,如下所示:

kubeseal --format=yaml --cert=public-key-cert.pem < secret.yaml > sealed-secret.yaml

导出私钥和解密

kubectl -n kube-system get secret -l sealedsecrets.bitnami.com/sealed-secrets-key=active -o yaml  | kubectl neat > allsealkeys.yml

解密文件

kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > sealed-secrets-key.yaml

kubeseal < sealed-secret.yaml --recovery-unseal --recovery-private-key sealed-secrets-key.yaml -o yaml

Conclusion 结论

Sealed Secrets 是一种在版本控制中管理 Kubernetes 机密的安全方法。在集群中存储加密密钥并解密机密。客户端无权访问加密密钥。

客户端使用 kubeseal CLI 工具生成 SealedSecret 保存加密数据的清单。应用文件后,服务器端控制器将识别新的密封密钥资源并对其进行解密以创建 Secret 资源。